
#include <BOpenGL>
#include <BProgram>
#include "member_BShader.h"
#include "member_BProgram.h"

using namespace BWE;

#define member					(*(member_BProgram*)_ptr)
#define member_allocate()		_ptr = new member_BProgram(this)
#define member_release()		delete (member_BProgram*)_ptr

BProgram::BProgram()
{
	member_allocate();
}
BProgram::BProgram(const BString& name) : BObject(name)
{
	member_allocate();
}
BProgram::~BProgram()
{
	member_release();
}

void BProgram::copy(const BProgram* other)
{
	BObject::setName(other->name());
	BObject::setEnabled(other->enabled());
	member.dirty = program_member(other)->dirty;
	member.object = program_member(other)->object;
	member.shaders = program_member(other)->shaders;
	member.uniforms = program_member(other)->uniforms;
}
BProgram* BProgram::clone() const
{
	BProgram* program = new BProgram();
	program->copy(this);
	return program;
}

void BProgram::addShader(BShader* shader)
{
	if (!member.shaders.contain(shader))
	{
		member.shaders.append(shader);
		member.dirty = true;
		emit(Signal_Dirty);
	}
}
void BProgram::removeShader(const BShader* shader)
{
	if (member.shaders.contain(shader))
	{
		member.shaders.remove(shader);
		member.dirty = true;
		member.dirty = true;
		emit(Signal_Dirty);
	}
}
void BProgram::removeShader(const BString& name)
{
	for (int i = 0; i < member.shaders.size(); i++)
	{
		BShader* shader = member.shaders[i];
		if (shader->name() == name)
		{
			member.shaders.remove(shader);
			member.dirty = true;
			emit(Signal_Dirty);
			break;
		}
	}
}

int BProgram::shaderCount() const
{
	return member.shaders.size();
}
BShader* BProgram::shader(int index)
{
	return member.shaders(index);
}
const BShader* BProgram::shader(int index) const
{
	return member.shaders(index);
}

void BProgram::addUniform(BUniform* uniform)
{
	if (!member.uniforms.contain(uniform))
	{
		member.uniforms.append(uniform);
		member.dirty = true;
		emit(Signal_Dirty);
	}
}
void BProgram::removeUniform(BUniform* uniform)
{
	if (member.uniforms.contain(uniform))
	{
		member.uniforms.remove(uniform);
		member.dirty = true;
		emit(Signal_Dirty);
	}
}

int BProgram::uniformCount() const
{
	return member.uniforms.size();
}
BUniform* BProgram::uniform(int index)
{
	return member.uniforms(index);
}
const BUniform* BProgram::uniform(int index) const
{
	return member.uniforms(index);
}

BUniform* BProgram::uniform(const char* name)
{
	for (int i = 0; i < member.uniforms.size(); i++)
	{
		BUniform* uniform = member.uniforms[i];
		if (uniform->name() == name)
			return uniform;
	}
	return 0;
}
const BUniform* BProgram::uniform(const char* name) const
{
	for (int i = 0; i < member.uniforms.size(); i++)
	{
		BUniform* uniform = member.uniforms[i];
		if (uniform->name() == name)
			return uniform;
	}
	return 0;
}

BUniform* BProgram::uniform(const BString& name)
{
	for (int i = 0; i < member.uniforms.size(); i++)
	{
		BUniform* uniform = member.uniforms[i];
		if (uniform->name() == name)
			return uniform;
	}
	return 0;
}
const BUniform* BProgram::uniform(const BString& name) const
{
	for (int i = 0; i < member.uniforms.size(); i++)
	{
		BUniform* uniform = member.uniforms[i];
		if (uniform->name() == name)
			return uniform;
	}
	return 0;
}

void BProgram::clear()
{
	if (member.object)
		glDeleteProgram(member.object);
	member.object = -1;
	member.dirty = true;
	emit(Signal_Dirty);
}

